using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
using Dapper;

public static class QueryBuilderExtensions
{
    /// <summary>
    /// 创建查询构建器
    /// </summary>
    public static IQueryBuilder<T> CreateQueryBuilder<T>(this IDbConnection connection, Expression<Func<T, bool>> whereExp = null)
    {
        var builder = new ExpressionQueryBuilder<T>();
        if (whereExp != null)
        {
            builder.Where(whereExp);
        }
        return builder;
    }
    
    /// <summary>
    /// 执行查询
    /// </summary>
    public static IEnumerable<T> Query<T>(this IDbConnection connection, IQueryBuilder<T> builder)
    {
        string sql = builder.GetQuery();
        return connection.Query<T>(sql, builder.Param);
    }
    
    /// <summary>
    /// 执行分页查询
    /// </summary>
    public static (IEnumerable<T> Data, int Total) QueryPaged<T>(this IDbConnection connection, IQueryBuilder<T> builder, int pageIndex, int pageSize)
    {
        // 获取总数
        string countSql = builder.GetCountQuery();
        int total = connection.QuerySingle<int>(countSql, builder.Param);
        
        // 获取分页数据
        string dataSql = $"{builder.GetQuery()} OFFSET {pageIndex * pageSize} ROWS FETCH NEXT {pageSize} ROWS ONLY";
        var data = connection.Query<T>(dataSql, builder.Param);
        
        return (data, total);
    }
    
    /// <summary>
    /// 执行单个查询
    /// </summary>
    public static T QuerySingle<T>(this IDbConnection connection, IQueryBuilder<T> builder)
    {
        string sql = builder.GetQuery();
        return connection.QuerySingleOrDefault<T>(sql, builder.Param);
    }
    
    /// <summary>
    /// 检查是否存在
    /// </summary>
    public static bool Exists<T>(this IDbConnection connection, IQueryBuilder<T> builder)
    {
        string sql = $"SELECT CASE WHEN EXISTS({builder.GetQuery()}) THEN 1 ELSE 0 END";
        return connection.QuerySingle<bool>(sql, builder.Param);
    }
    
    /// <summary>
    /// 获取数量
    /// </summary>
    public static int Count<T>(this IDbConnection connection, IQueryBuilder<T> builder)
    {
        string sql = builder.GetCountQuery();
        return connection.QuerySingle<int>(sql, builder.Param);
    }
}